fix: NestJS discriminator guards + EXPOSES edge target#15
Conversation
…her query Added GraphStore.findEndpointNeighborsBatch() that fetches all endpoint neighbors for a list of node IDs in one MATCH ... WHERE n.id IN $nodeIds query, eliminating up to 50 separate findNeighbors() calls per invocation. QueryService.findRelatedEndpoints() now separates the direct-endpoint pass from the neighbor pass, using the new batch method for the latter. Deduplication and connected_via semantics are preserved. Added 3 unit tests covering: batch usage (verifying findNeighbors is never called), direct endpoint matches, and deduplication. Co-Authored-By: Paperclip <noreply@paperclip.ing>
…s for search Store label_lower and fqn_lower on every node during bulkSave() so that case-insensitive search can hit a B-tree index instead of doing a full graph scan with toLower() on both sides of the CONTAINS predicate. - nodeToProps(): adds label_lower/fqn_lower to the Neo4j property map - bulkSave(): creates indexes on label_lower and fqn_lower - EnrichCommand: creates label_lower/fqn_lower indexes alongside kind/layer/module/filePath - GraphStore.search(text, limit): lowercase input, query against pre-lowered props - GraphRepository.search(): same query update (SDN path) - nodeFromNeo4j(): label_lower/fqn_lower implicitly excluded (no prop_ prefix) All 1459 tests pass. Co-Authored-By: Paperclip <noreply@paperclip.ing>
…RE and ENDPOINT nodes Implements RAN-61. GuardLinker uses file-path proximity (same file = match) to infer that guards and middleware in a file protect endpoints in that file. This surfaces security architecture in the graph for Spring @PreAuthorize, @secured, DjangoAuth, FastAPIAuth, NestJSGuards, and generic middleware nodes. - 9 unit tests: positive match, middleware, class-level, cross-file negative, no-guards, no-endpoints, duplicate avoidance, null filePath, determinism - 1468 total tests pass, 0 failures Co-Authored-By: Paperclip <noreply@paperclip.ing>
…tection - Add GUARD, MIDDLEWARE, TOPIC, QUEUE, EVENT, MESSAGE_QUEUE to ENTRY_POINT_KINDS so they are never flagged as dead code (they are entry points / cross-cutting concerns) - Remove invalid 'uses' edge kind from SEMANTIC_EDGE_KINDS (not a valid EdgeKind) - Add 'protects' to SEMANTIC_EDGE_KINDS so PROTECTS edges from GuardLinker count as semantic usage when determining reachability - Add two new tests: verifying new entry point kinds are excluded, and verifying 'protects' is included / 'uses' is excluded from semantic edge kinds Co-Authored-By: Paperclip <noreply@paperclip.ing>
- NestJSControllerDetector: bail out early if no @nestjs/ import to prevent false positives on Angular controllers and generic TypeScript - NestJSGuardsDetector: bail out early if no @nestjs/ import to prevent false positives on any TypeScript with canActivate() - NestJSControllerDetector: add edge.setTarget(node) on EXPOSES edges — previously missing, causing all class→endpoint edges to be silently dropped by GraphBuilder Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
Code Review — Principal EngineerCI passes and the core bugfixes are correctly implemented. However, there is one critical defect in the scope-expanded code that must be fixed before this can merge. ✅ Approved ChangesBug 1 — NestJS discriminator guards: Both Bug 2 — EXPOSES edge target: GuardLinker: Well-structured, correct pattern ( Search optimization (label_lower/fqn_lower): Pre-lowered properties written at bulk-save time, indexed in both Dead code improvements: Removing 🔴 Critical Bug — Must Fix Before MergeFile: Current code: "MATCH (n:CodeNode)-[]-(m:CodeNode) "
+ "WHERE n.id IN $nodeIds AND m.kind IN ['ENDPOINT', 'WEBSOCKET_ENDPOINT'] "Problem: Node kinds are stored lowercase in Neo4j ( Unit tests miss this because they mock Fix: "MATCH (n:CodeNode)-[]-(m:CodeNode) "
+ "WHERE n.id IN $nodeIds AND m.kind IN ['endpoint', 'websocket_endpoint'] "This matches all other kind comparisons in the file ( Fix this one line, then this PR is approved. |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code |


Summary
NestJSControllerDetectorandNestJSGuardsDetectornow bail out early when no@nestjs/import is present, eliminating false positives on Angular components, custom TypeScript decorators, and any file withcanActivate()methods. Aligns with the CLAUDE.md requirement: "Framework detectors MUST have discriminator guards."NestJSControllerDetectorwas building EXPOSES edges without callingedge.setTarget(node). SinceGraphBuilder.flush()requires a non-null target, all NestJS controller→endpoint edges were silently dropped. Fixed by addingedge.setTarget(node)matching the pattern used bySpringRestDetectorandJaxrsDetector.Test plan
detectsNestJSControllerupdated to include@nestjs/commonimport — verifies positive detection + EXPOSES edges have non-null targetsdetectsGuardsAndRolesupdated to include@nestjs/commonimport — verifies positive guard detectionnoMatchWithoutNestJSImport— verifies NestJSControllerDetector rejects files missing@nestjs/importnoMatchOnAngularComponent— verifies Angular@Componentfiles are not misidentifiednoMatchWithoutNestJSImportin guards test — verifiescanActivate()without NestJS import is rejectedmvn test→ 1473 tests, 0 failuresCloses RAN-67
🤖 Generated with Claude Code